package sys

import (
	"context"
	"errors"
	"fmt"
	"github.com/google/wire"
	"sieve_admin_server/app/dao"
	"sieve_admin_server/app/dao/country"
	"sieve_admin_server/app/dao/user"
	"sieve_admin_server/app/schema"
	"strconv"
	"time"
)

var (
	CountrySet = wire.NewSet(wire.Struct(new(CountrySrv), "*"))
)

type CountrySrv struct {
	CountryRepo *dao.CountryRepo
}

func (a *CountrySrv) Create(ctx context.Context, item map[string]interface{}) interface{} {

	var (
		now = time.Now().Unix()
		def = map[string]interface{}{
			"create_at":  now,
			"updated_at": now,
		}
	)

	if b := a.checkExist(ctx, item["short_name"].(string)); b {
		return errors.New(fmt.Sprintf("已经存在的国家:%+v", item["short_name"]))
	}

	for k, v := range def {
		item[k] = v
	}

	return a.CountryRepo.Create(ctx, item)
}

func (a *CountrySrv) checkExist(ctx context.Context, shortName string) bool {

	var (
		reqArgs = map[string]interface{}{
			"short_name": shortName,
		}

		p = schema.PaginationParam{
			OnlyData: true,
		}
	)

	req := a.Query(context.Background(), reqArgs, p)
	if req != nil {
		if _, ok := req.(error); ok {
			return true
		}
	}

	for range req.(map[string]interface{})["list"].([]interface{}) {

		return true
	}

	return false
}

func (a *CountrySrv) Query(ctx context.Context, reqArgs map[string]interface{}, p schema.PaginationParam) interface{} {

	type columnType struct {
		ID               int64   `json:"id"`
		FullName         string  `json:"full_name"`
		ShortName        string  `json:"short_name"`
		AreaCode         string  `json:"area_code"`
		NumberBitCount   int64   `json:"number_bit_count"`
		DisableSieveList int64   `json:"disable_sieve_list"`
		Status           int64   `json:"status"`
		Creator          int64   `json:"creator"`
		CreatorName      *string `json:"creator_name"`
		CreateAt         int64   `json:"create_at"`
		UpdatedAt        int64   `json:"updated_at"`
		Deleted          int     `json:"deleted"`
	}

	var (
		countryTableName = country.Country{}.TableName()
		userTableName    = user.User{}.TableName()
		joinString       = fmt.Sprintf(
			`
			LEFT JOIN %v ON %v.id = %v.creator and %v.deleted = 0`,
			userTableName,
			userTableName,
			countryTableName,
			userTableName,
		)
		repKeys = []string{
			fmt.Sprintf("%v.id as id", countryTableName),
			fmt.Sprintf("%v.full_name as full_name", countryTableName),
			fmt.Sprintf("%v.short_name as short_name", countryTableName),
			fmt.Sprintf("%v.area_code as area_code", countryTableName),
			fmt.Sprintf("%v.number_bit_count as number_bit_count", countryTableName),
			fmt.Sprintf("%v.disable_sieve_list as disable_sieve_list", countryTableName),
			fmt.Sprintf("%v.status as status", countryTableName),
			fmt.Sprintf("%v.creator as creator", countryTableName),
			fmt.Sprintf("%v.account as creator_name", userTableName),
			fmt.Sprintf("%v.create_at as create_at", countryTableName),
			fmt.Sprintf("%v.updated_at as updated_at", countryTableName),
		}
	)

	ctx = context.WithValue(
		context.WithValue(
			context.WithValue(ctx, "join", joinString),
			"column_types", columnType{},
		), "order_by", "id ASC")

	req, err := a.CountryRepo.Query(ctx, reqArgs, p, repKeys)
	if err != nil {
		return err
	}
	return req
}

func (a *CountrySrv) QueryCountryList(ctx context.Context, reqArgs map[string]interface{}, repKeys []string) interface{} {

	reqArgs["status"] = 1
	req, err := a.CountryRepo.Query(context.Background(), reqArgs, schema.PaginationParam{}, repKeys)
	if err != nil {
		return err
	}
	return req
}

func (a *CountrySrv) Enable(ctx context.Context, reqArgs map[string]interface{}) error {

	var (
		now        = time.Now().Unix()
		updateKeys = map[string]interface{}{
			"updated_at": now,
			"status":     1,
		}
		queryKeys = map[string]interface{}{
			"id": reqArgs["id"],
		}
	)

	return a.CountryRepo.Update(ctx, updateKeys, queryKeys)
}

func (a *CountrySrv) Disable(ctx context.Context, reqArgs map[string]interface{}) error {

	var (
		now        = time.Now().Unix()
		updateKeys = map[string]interface{}{
			"updated_at": now,
			"status":     2,
		}
		queryKeys = map[string]interface{}{
			"id": reqArgs["id"],
		}
	)

	return a.CountryRepo.Update(ctx, updateKeys, queryKeys)
}

func (a *CountrySrv) Update(ctx context.Context, reqArgs map[string]interface{}) error {

	var (
		now        = time.Now().Unix()
		updateKeys = map[string]interface{}{
			"updated_at":       now,
			"full_name":        reqArgs["full_name"],
			"short_name":       reqArgs["short_name"],
			"number_bit_count": reqArgs["number_bit_count"],
		}
		queryKeys = map[string]interface{}{
			"id": reqArgs["id"],
		}
	)

	return a.CountryRepo.Update(ctx, updateKeys, queryKeys)
}

func (a *CountrySrv) Delete(ctx context.Context, reqArgs map[string]interface{}) interface{} {

	var (
		id, _ = strconv.ParseUint(fmt.Sprintf("%v", reqArgs["id"]), 10, 64)
	)

	return a.CountryRepo.SoftDelete(ctx, id)
}
